iT邦幫忙

2023 iThome 鐵人賽

DAY 7
0
自我挑戰組

卡卡嗯的機率實驗筆記系列 第 7

水塘抽樣 Reservoir Sampling

  • 分享至 

  • xImage
  •  

今天來聊聊產生隨機排列與組合的方法。

先來個簡單版:若我們今天想要產生一個隨機排列,那麼我們可以考慮以下的 Fisher-Yates 演算法:假若一開始陣列中有 n 個元素,分別為 1 到 n。現在依序考慮每一個 i = 1, 2, …, n,我們隨機地將第 i 個位置的元素與任何一個 i~n 之間的元素交換。可以用數學歸納法證明,當我們做到第 i 個位置的時候,任何當前留在 i ~n 位置的元素被交換到第 i 個位置的機會均等。

比方說,我們現在來實驗這個演算法,看看數字 k=1 出現在各個位置的分佈是否接近均勻。

# 一次實驗,回傳數字 k 出現的位置。
def simulate_shuffle(n, k):
    arr = [x for x in range(1, n+1)]
    for i in range(n):
        j = np.random.randint(i, n)  # 隨機選擇一個位置交換。
        arr[i], arr[j] = arr[j], arr[i]
    return arr.index(k)

        
rep = 10000  # 實驗次數
n = 100      # 陣列大小
k = 1        # 關心的數值
results = [simulate_shuffle(n, k) for _ in range(rep)]

# 把結果繪製出來
# plt.figure(figsize=(8, 1))
plt.bar(*np.unique(results, return_counts=True))
ax = plt.gca()
ax.bar_label(ax.containers[0], label_type='edge')
ax.set_title(f"隨機排列", fontname='LiHei Pro')
plt.show()

https://ithelp.ithome.com.tw/upload/images/20230922/201123768TMDJLj0rx.png

水塘抽樣是產生隨機組合的方法,其目的是要均勻地抓出水塘中隨意 k 個不同的數字形成的集合。它可以視為厲害版的非重複抽樣:所需要的記憶體其實只需要 O(k) 這麼多,這個對於串流式計算是相當有助益的。

方法如下:我們紀錄一個長度為 k 的陣列。然後對於索引為 i 的元素,我們決定一個 0~i 之間的隨機數,並且僅有在該數字介於 0 ~ k-1 之間的時候,將原陣列內容替換為 i 元素。如此一來,這些一個一個被考慮的資料就不一定要總是留在記憶體裡面了!

# 一次實驗,在 n 個數字中,選 k 個數字的集合。
def simulate_reservoir(n, k):
    arr = [i for i in range(k)]
    for val in range(k, n):
        i = np.random.randint(0, val+1)
        if i < k:
            arr[i] = val
    
    arr.sort()
    return str(arr)

        
rep = 100000  # 實驗次數
n = 10       # 陣列大小
k = 3        # 關心的數值
results = [simulate_reservoir(n, k) for _ in range(rep)]

# 把結果繪製出來
# plt.figure(figsize=(8, 1))
plt.bar(*np.unique(results, return_counts=True))
ax = plt.gca()
ax.bar_label(ax.containers[0], label_type='edge')
ax.set_title(f"隨機排列", fontname='LiHei Pro')
plt.show()

https://ithelp.ithome.com.tw/upload/images/20230922/201123764AQ3IMYKLo.png

感覺今天的圖片們看起來都滿可怕的XD


上一篇
拒絕抽樣 Rejection Sampling
系列文
卡卡嗯的機率實驗筆記7
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言